<?php

namespace App\Http\Controllers\Front;

use App\Http\Controllers\Controller;
use App\Model\BankCard;
use App\Model\PutForward;
use App\Model\Setting;
use App\Model\SmsMsg;
use App\Model\UserBill;
use App\Model\UserBonusCount;
use App\Model\UserBonusTurnWalletLog;
use App\Model\UserWalletRecordLog;
use App\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Swagger\Annotations as SWG;

class AccountController extends Controller
{
	/**
	 * @var User
	 */
	private $user;

	public function __construct()
	{
		$this->user = Auth::user();
	}

	/**
	 * @SWG\Post(
	 *     path="/front/account/bind_phone",
	 *     tags={"账户相关"},
	 *     summary="绑定手机",
	 *     description="绑定手机或者修改绑定手机",
	 *     consumes={"application/x-www-form-urlencoded"},
	 *     produces={"application/json"},
	 *     @SWG\Parameter(ref="#/parameters/auth"),
	 *     @SWG\Parameter(name="phone_number", in="formData", required=true, type="string", description="手机号"),
	 *     @SWG\Parameter(name="code", in="formData", required=true, type="string", description="短信验证码"),
	 *     @SWG\Response(response="200", description="绑定成功"),
	 *     @SWG\Response(response="401", description="没有登录")
	 * )
	 */
	public function bindPhone(Request $request, SmsMsg $msg)
	{
		$this->validate($request, [
			'phone_number' => [
				'regex:/^1[345789][0-9]{9}$/',
				'unique:users,phone'
			],
			'code' => 'size:6'
		], [
			'phone_number.regex' => '手机号格式不正确',
			'phone_number.unique' => '该手机已被注册',
			'code.size' => '验证码错误'
		]);
		$phone = $request->input('phone_number');

		$msg->validate($phone, $request->input('code'));
		$user = User::where('phone', $phone)->first();
		if ($user && $user->phone == $phone) {
			return $this->fail('手机号已存在');
		}
		$user = $this->user;
		if (!$user->update(['phone' => $phone])) {
			return $this->error('修改失败，请稍后重试');
		}
		return $this->success();
	}


	/**
	 * @SWG\Get(
	 *     path="/front/account/wallet",
	 *     tags={"账户相关"},
	 *     summary="钱包",
	 *     description="钱包信息",
	 *     produces={"application/json"},
	 *     @SWG\Parameter(ref="#/parameters/auth"),
	 *     @SWG\Response(
	 *          response="200",
	 *          description="钱包金额信息",
	 *          @SWG\Schema(
	 *              @SWG\Property(property="money", type="number", description="余额")
	 *          )
	 *      )
	 * )
	 */
	public function wallet()
	{
		return $this->renderJson(['money' => $this->user->money]);
	}

	/**
	 * @SWG\Get(
	 *     path="/front/account/wallet/bill",
	 *     tags={"账户相关"},
	 *     summary="钱包明细",
	 *     description="钱包信息",
	 *     produces={"application/json"},
	 *     @SWG\Parameter(ref="#/parameters/auth"),
	 *     @SWG\Response(
	 *          response="200",
	 *          description="明细",
	 *          @SWG\Schema(
	 *              type="array",
	 *              @SWG\Items(
	 *                  @SWG\Property(property="id", type="integer", description="id"),
	 *                  @SWG\Property(property="type", type="integer", description="1：奖励金转入，2：克隆收益,3:体现失败，4：微信充值会员，5提现成功或者申请提现，6克隆支出，7开通会员，8平台充值会员"),
	 *                  @SWG\Property(property="cate", type="integer", description="1收入0支出"),
	 *                  @SWG\Property(property="money", type="number", description="金额"),
	 *                  @SWG\Property(property="describe", type="string", description="描述"),
	 *                  @SWG\Property(property="created_at", type="string", format="date", description="时间"),
	 *              )
	 *          )
	 *      )
	 * )
	 */
	public function bill(UserBill $userBill)
	{
		$bill = $userBill->select('id', 'type', 'income_type', 'money', 'created_at', 'describe')
			->where('user_id', '=', $this->user->id)->orderByDesc('created_at')
			->whereIn('type', [1, 2, 3, 5, 6, 7])
			->when(\request('type'), function ($query, $value) {
				$query->where('type', $value);
			})
			->paginate(request('limit', 15));

		return $this->renderJson($bill->toArray());
	}

	/**
	 * @SWG\Get(
	 *     path="/front/account/wallet/cash",
	 *     tags={"账户相关"},
	 *     summary="银行卡信息",
	 *     description="银行卡信息",
	 *     produces={"application/json"},
	 *     @SWG\Parameter(ref="#/parameters/auth"),
	 *     @SWG\Response(
	 *          response="200",
	 *          description="钱包银行卡信息",
	 *          @SWG\Schema(
	 *              @SWG\Property(property="card_name", type="string", description="持卡人"),
	 *              @SWG\Property(property="card_no", type="string", description="卡号"),
	 *              @SWG\Property(property="availableAmount", type="number", description="可提现金额"),
	 *          )
	 *      )
	 * )
	 */
	public function cashInfo(BankCard $bankCard)
	{
		$bank = $bankCard->where('user_id', '=', $this->user->id)->first();
		if ($bank == null) {
			return $this->renderJson();
		}
		$data = [
			'card_name' => $bank ? $bank->bank_name : '',
			'card_no' => $bank ? $bank->card_no : '',
			'availableAmount' => $this->user->money
		];

		return $this->renderJson($data);
	}

	/**
	 * @SWG\Post(
	 *     path="/front/account/wallet/cash",
	 *     tags={"账户相关"},
	 *     summary="钱包申请提现",
	 *     description="钱包提现",
	 *     consumes={"application/x-www-form-urlencoded"},
	 *     produces={"application/json"},
	 *     @SWG\Parameter(ref="#/parameters/auth"),
	 *     @SWG\Parameter(name="amount", in="formData", required=true, type="number", description="需要提现的金额"),
	 *     @SWG\Parameter(name="pwd", in="formData", required=true, type="string", description="支付密码"),
	 *     @SWG\Parameter(name="bank_card_no", in="formData", required=true, type="string", description="收款卡号"),
	 *     @SWG\Parameter(name="bank_name", in="formData", required=true, type="string", description="收款人"),
	 *     @SWG\Response(
	 *          response="200",
	 *          description="提现申请成功"
	 *      )
	 * )
	 */
	public function cash(PutForward $forward)
	{
		$this->validate(\request(), [
			'amount' => 'required|numeric',
			'pwd' => 'required|integer',
			'bank_card_no' => 'required',
			'bank_name' => 'required'
		], [
			'pwd.required' => '支付密码不能为空',
			'amount.required' => '金额不能为空',
			'amount.numeric' => '金额必须为数字',
			'pwd.integer' => '支付密码错误'
		]);
		$amount = request('amount');
		$pwd = request('pwd');
		$cache = app('cache');
		$key = 'cash' . '|' . Auth::id() . '|' . 'pay_pwd' . '|' . request()->ip();
		$attempts = $cache->get($key, 0);
		if ($attempts > 1 && $cache->has($key . ':timer')) {
			return $this->fail('支付密码错误次数太多,请稍后重试!');
		}
		if (strlen($pwd) != 6) {
			return $this->fail('支付密码格式错误');
		}
		if (empty($this->user->payment_password)) {
			return $this->fail('你还未设置支付密码，请先设置');
		}

		if (!password_verify($pwd, $this->user->payment_password)) {
			$added = $cache->add($key . ':timer', 0, 60);
			$hit = (int)$cache->increment($key);
			if (!$added && $hit == 1) {
				$cache->put($key, 1, 60);
			}
			$attempts = $cache->get($key, 0);
			if ($attempts >= 2) {
				return $this->fail('支付密码错误次数太多,请稍后重试!');
			}
			return $this->fail("支付密码错误,你还剩" . (2 - $attempts) . '次尝试机会');
		}
//        $vip = DB::table('user_grade')->select('vip_fee_config.type')->join('vip_fee_config', 'user_grade.vip_fee_config_id','=','vip_fee_config.id')->where('user_grade.user_id','=',$this->user->id)->first();
//        if ($vip == null){
//            return $this->fail('请先成为会员才能提现');
//        }
//        if ($vip->type != 1){
//            if ($amount < 50){
//                return $this->fail('非砖石会员提现金额不能小于50');
//            }
//        }
		$cashWithdrawalLimit = Setting::getValue('cash-withdrawal-limi')['value'] ?: 20;
		if ($amount < $cashWithdrawalLimit) {
			return $this->fail("提现金额不能少于{$cashWithdrawalLimit}元");
		}
		if ($amount <= 0) {
			return $this->fail('金额错误');
		}
		try {
			DB::beginTransaction();
			//悲观锁
			$user = User::where('id', $this->user->id)->lockForUpdate()->first();
			if ($user->money < $amount) {
				return $this->fail('余额不足');
			}
			$bank = BankCard::where('card_no', request('bank_card_no'))->where('user_id', $this->user->id)->first();
			$name = $this->user->cards ? $this->user->cards->user_name : '';
			if (request()->has('name')) {
				$name = request('name');
			} else if ($bank->name) {
				$name = $bank->name;
			}
			//扣除金额
			$r1 = $user->decrement('money', $amount);
			$forward->user_id = $this->user->id;
			$forward->phone = $this->user->phone;
			$forward->title = '会员提现';
			$forward->name = $name;
			$forward->identity = $this->user->type;
			$forward->amount = $amount;
			$forward->bank_card_no = request('bank_card_no');
			$forward->bank_name = request('bank_name');
			$forward->bank_branch = request('bank_name');
			$forward->expect_at = date('Y-m-d H:i:s', time());
			$r2 = $forward->save();
			UserBill::create([
				'user_id' => Auth::id(),
				'type' => 5,
				'income_type' => 0,
				'describe' => '申请提现',
				'money' => $amount
			]);
			if (!$r1 || !$r2) {
				DB::rollBack();
				return $this->error();
			}
			DB::commit();
			return $this->success();
		} catch (\Exception $e) {
			DB::rollBack();
			return $this->error();
		}

	}

	/**
	 * @SWG\Post(
	 *     path="/front/account/shift-to",
	 *     tags={"账户相关"},
	 *     summary="奖励金转入余额",
	 *     description="转入余额",
	 *     consumes={"application/x-www-form-urlencoded"},
	 *     produces={"application/json"},
	 *     @SWG\Parameter(ref="#/parameters/auth"),
	 *     @SWG\Parameter(name="money", in="formData", required=true, type="number", description="需要转入的金额"),
	 *     @SWG\Response(
	 *          response="200",
	 *          description="转入余额成功"
	 *      )
	 * )
	 */
	public function shiftTo()
	{
		$this->validate(\request(), [
			'money' => 'required'
		]);
		if ($this->user->is_vip($this->user->id) === false) {
			return $this->fail("此功能需要开通会员");
		}
		try {
			DB::beginTransaction();
			//佣金
			$user = User::where('id', $this->user->id)->lockForUpdate()->first();
			$current = $user->currentCommission;
			$money = request('money');
			if ($current <= 0) {
				return $this->fail('奖励金不足');
			}
			if ($money > $current) {
				return $this->fail('奖励金不足');
			}
			$r1 = $user->increment('money', $money);
			$r2 = $user->increment('changeCommission', $money);
			$r3 = $user->decrement('currentCommission', $money);
			$r4 = $this->user->save();
			if (!$r1 || !$r2 || !$r3 || !$r4) {
				DB::rollBack();
				return $this->error();
			}
			//TODO 日志
			$id = UserBonusTurnWalletLog::insertGetId([
				'title' => '奖励金转入余额',
				'content' => '奖励金转入余额',
				'money' => $money,
				'user_id' => $this->user->id,
				'created_at' => Carbon::now(),
			]);
			UserWalletRecordLog::insert([
				'type' => 1,
				'income_type' => 1,
				'user_id' => $this->user->id,
				'money' => $money,
				'relation_id' => $id,
				'describe' => '奖励金转入',
				'created_at' => Carbon::now(),
			]);
			UserBonusCount::insert([
				'type' => 3,
				'income_type' => 0,
				'user_id' => $this->user->id,
				'money' => $money,
				'relation_id' => $id,
				'describe' => '转入余额',
				'created_at' => Carbon::now(),
			]);
			DB::commit();
			return $this->success();
		} catch (\Exception $e) {
			DB::rollBack();
			return $this->error($e->getMessage());
		}
	}

	/**
	 * @SWG\Post(
	 *     path="/front/account/validatePymPwd",
	 *     tags={"账户相关"},
	 *     summary="验证支付密码",
	 *     description="验证支付密码",
	 *     consumes={"application/x-www-form-urlencoded"},
	 *     produces={"application/json"},
	 *     @SWG\Parameter(ref="#/parameters/auth"),
	 *     @SWG\Parameter(name="pwd", in="formData", required=true, type="string", description="支付密码"),
	 *     @SWG\Response(
	 *          response="200",
	 *          description="验证成功"
	 *      )
	 * )
	 */
	public function validatePymPwd(Request $request)
	{
		$this->validate($request, [
			'pwd' => 'required'
		]);

		if (password_verify($request->input('pwd'), $this->user->payment_password)) {
			return $this->success();
		}
		return $this->fail('密码错误');
	}

	/**
	 * @SWG\Post(
	 *     path="/front/account/resetPaymentPwd",
	 *     tags={"账户相关"},
	 *     summary="修改支付密码",
	 *     description="修改支付密码",
	 *     consumes={"application/x-www-form-urlencoded"},
	 *     produces={"application/json"},
	 *     @SWG\Parameter(ref="#/parameters/auth"),
	 *     @SWG\Parameter(name="old_pwd", in="formData", required=true, type="string", description="旧支付密码"),
	 *     @SWG\Parameter(name="new_pwd", in="formData", required=true, type="string", description="新支付密码"),
	 *     @SWG\Response(
	 *          response="200",
	 *          description="修改成功"
	 *      )
	 * )
	 */
	public function resetPymPwd(Request $request)
	{
		$this->validate($request, [
			'old_pwd' => 'required',
			'new_pwd' => 'required'
		], [
			'old_pwd.required' => '请输入旧支付密码'
		]);
		if (!password_verify($request->input('old_pwd'), $this->user->payment_password)) {
			return $this->fail('支付密码错误');
		}
		//修改支付密码
		$user = $this->user;
		$user->payment_password = bcrypt($request->input('new_pwd'));
		$user->save();
		return $this->success();
	}

	/**
	 * @SWG\Post(
	 *     path="/front/account/validatePaymentSms",
	 *     tags={"账户相关"},
	 *     summary="验证支付密码短信",
	 *     description="支付密码短信验证",
	 *     consumes={"application/x-www-form-urlencoded"},
	 *     produces={"application/json"},
	 *     @SWG\Parameter(ref="#/parameters/auth"),
	 *     @SWG\Parameter(name="phone", in="formData", required=true, type="string", description="手机号"),
	 *     @SWG\Parameter(name="code", in="formData", required=true, type="string", description="短信验证码"),
	 *     @SWG\Response(
	 *          response="200",
	 *          description="验证成功",
	 *          @SWG\Schema(
	 *              @SWG\Property(property="sign", type="string", description="后面需要用到的签名")
	 *          )
	 *      )
	 * )
	 */
	public function validatePymSms(Request $request, SmsMsg $msg)
	{
		$this->validate($request, [
			'phone' => [
				'regex:/^1[345789][0-9]{9}$/'
			],
			'code' => 'required'
		], [
			'phone.required' => '手机号不能为空',
			'phone.regex' => '手机号错误'
		]);
		$phone = $request->input('phone');
		$code = $request->input('code');
		$msg->validate($phone, $code, 5);
		//验证通过，写入临时
		$validatePymSms = Cache::get('validatePymSms');
		$hash = md5("{$phone}-{$code}-{$this->user->id}-" . time());
		$validatePymSms['id-' . $this->user->id] = $hash;
		Cache::put('validatePymSms', $validatePymSms);
		return $this->renderJson(['sign' => $hash]);

	}

	/**
	 * @SWG\Post(
	 *     path="/front/account/setPaymentPwd",
	 *     tags={"账户相关"},
	 *     summary="设置支付密码",
	 *     description="设置支付密码",
	 *     consumes={"application/x-www-form-urlencoded"},
	 *     produces={"application/json"},
	 *     @SWG\Parameter(ref="#/parameters/auth"),
	 *     @SWG\Parameter(name="sign", in="formData", required=true, type="string", description="短信验证获取到的签名"),
	 *     @SWG\Parameter(name="pwd", in="formData", required=true, type="string", description="需要设置的支付密码"),
	 *     @SWG\Response(
	 *          response="200",
	 *          description="设置成功"
	 *      )
	 * )
	 */
	public function setPymPwd(Request $request)
	{
		$this->validate($request, [
			'sign' => 'required',
			'pwd' => 'required'
		], [
			'sign.required' => '签名错误'
		]);

		$validatePymSms = Cache::get('validatePymSms');
		$hash = $validatePymSms['id-' . $this->user->id];
		if ($request->input('sing') != $hash) {
			$this->fail('签名错误');
		}
		$user = $this->user;
		$user->payment_password = bcrypt($request->input('pwd'));
		$user->save();
		unset($validatePymSms['id-' . $this->user->id]);
		Cache::put('validatePymSms', $validatePymSms);
		return $this->success();
	}

	/**
	 * @SWG\Post(
	 *     path="/front/account/validateOldPhone",
	 *     tags={"账户相关"},
	 *     summary="验证旧手机号",
	 *     description="验证旧手机号",
	 *     consumes={"application/x-www-form-urlencoded"},
	 *     produces={"application/json"},
	 *     @SWG\Parameter(ref="#/parameters/auth"),
	 *     @SWG\Parameter(name="phone", in="formData", required=true, type="string", description="手机号"),
	 *     @SWG\Parameter(name="code", in="formData", required=true, type="string", description="短信验证码"),
	 *     @SWG\Response(
	 *          response="200",
	 *          description="验证成功",
	 *          @SWG\Schema(
	 *              @SWG\Property(property="sign", type="string", description="后面需要用到的签名")
	 *          )
	 *      )
	 * )
	 */
	public function validateOldPhone(Request $request, SmsMsg $msg)
	{
		$this->validate($request, [
			'phone' => [
				'regex:/^1[345789][0-9]{9}$/'
			],
			'code' => 'required'
		], [
			'phone.required' => '手机号不能为空',
			'phone.regex' => '手机号错误'
		]);

		$phone = $request->input('phone');
		$code = $request->input('code');
		$msg->validate($phone, $code, 4);
		//验证通过，写入临时
		$validateBindPhoneSms = Cache::get('validateBindPhoneSms');
		$hash = md5("{$phone}-{$code}-{$this->user->id}-" . time());
		$validateBindPhoneSms['id-' . $this->user->id] = $hash;
		Cache::put('validateBindPhoneSms', $validateBindPhoneSms);
		return $this->renderJson(['sign' => $hash]);
	}

	/**
	 * @SWG\Post(
	 *     path="/front/account/bindNewPhone",
	 *     tags={"账户相关"},
	 *     summary="设置支付密码",
	 *     description="设置支付密码",
	 *     consumes={"application/x-www-form-urlencoded"},
	 *     produces={"application/json"},
	 *     @SWG\Parameter(ref="#/parameters/auth"),
	 *     @SWG\Parameter(name="sign", in="formData", required=true, type="string", description="短信验证获取到的签名"),
	 *     @SWG\Parameter(name="code", in="formData", required=true, type="string", description="新手机验证码"),
	 *     @SWG\Parameter(name="phone", in="formData", required=true, type="string", description="新手机"),
	 *     @SWG\Response(
	 *          response="200",
	 *          description="设置成功"
	 *      )
	 * )
	 */
	public function changePhone(Request $request, SmsMsg $msg)
	{
		$this->validate($request, [
			'sign' => 'required',
			'code' => 'required',
			'phone' => [
				'regex:/^1[345789][0-9]{9}$/'
			]
		], [
			'sign.required' => '签名错误',
			'phone.regex' => '手机号错误'
		]);
		$validateBindPhoneSms = Cache::get('validateBindPhoneSms');
		$hash = $validateBindPhoneSms['id-' . $this->user->id];
		if ($request->input('sing') != $hash) {
			$this->fail('签名错误');
		}
		$phone = $request->input('phone');
		$code = $request->input('code');
		$msg->validate($phone, $code, 4);
		//验证手机号是否被使用
		$p = User::where('phone', $phone)->first();
		if ($p != null) {
			return $this->fail('改手机号已被使用');
		}
		$user = $this->user;
		$user->phone = $phone;
		$user->save();
		return $this->success();
	}
}
